//=============================================================================
//
//   Copyright (C) 2020 All rights reserved.
//
//   Filename:		elastic.rs
//
//   Author: Wang Zhecheng - wangzhecheng@yeah.net
//
//   Date: 2020-10-12 13:35
//
//   Last Editors: Wang Zhecheng - wangzhecheng@yeah.net
//
//   Last modified:	2020-11-06 18:27
//
//   Description:
//
//=============================================================================
use crate::arith::tensor::{Strain, Stress};
use crate::dimension::DimType;
use crate::material::{MaterialCommonParameter, MaterialLike};
use crate::Real;
use crate::util::{record::Record, HasName, Indexable};
use nalgebra::allocator::Allocator;
use nalgebra::{DefaultAllocator, MatrixN};
use serde::{Deserialize, Serialize};
use std::marker::PhantomData;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Elastic<DT: DimType> {
    id: Option<usize>,
    volume_weight: Real,
    friction_angle: Real,
    dilation_angle: Real,
    cohesion: Real,
    #[serde(rename = "permeability")]
    perm: nalgebra::Vector3<Real>,
    zeta: Real,
    #[serde(rename = "K_IC")]
    k_ic: Real,
    elastic_modulus: Real,
    elastic_poisson: Real,
    #[serde(skip)]
    _marker: PhantomData<DT>,
}

material_parameter_impl!(Elastic<DT: DimType>);

impl<DT: DimType> MaterialLike<DT> for Elastic<DT> {
    fn get_dee_matrix(&self, _s: &Stress<DT>, _rec: &Record<DT>) -> MatrixN<Real, DT::DimVoigt>
    where
        DefaultAllocator: Allocator<Real, DT::DimVoigt, DT::DimVoigt>,
    {
        self.get_elastic_matrix()
    }
    /// get the value of the yield function
    fn get_yield_function(&self, _s: &Stress<DT>, _rec: &Record<DT>) -> Real {
        -1 as Real
    }
    /// update stress history related parameters for given sigma and epsilon (only override in hardening/softening material for changing yield function)
    fn update_paremeter(&self, _s: &Stress<DT>, _dpe: &Strain<DT>, _rec: &Record<DT>) {}
}

#[test]
fn serde() {
    use crate::dimension::PlaneStrain;
    let data = r#"
        {
            "id": 2,
            "type": "elastic",
            "volume_weight": 19,
            "friction_angle": 30,
            "dilation_angle": 30,
            "cohesion": 10,
            "permeability": [1e-5,1e-5, 1e-5 ],
            "zeta": 0.1,
            "K_IC": 2.9,
            "elastic_modulus": 1000000.0,
            "elastic_poisson": 0.3
        }"#;
    let mat: Elastic<PlaneStrain> = serde_json::from_str(data).unwrap();
    assert_eq!(mat.get_volume_weight(), 19 as Real);
    assert_eq!(mat.get_elastic_poisson(), 0.3 as Real);
}
